home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / AUTH.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-18  |  8.7 KB  |  352 lines

  1. /* Authentication functions - taken from files.c */
  2. #include "global.h"
  3. #include "ctype.h"
  4. #include "commands.h"
  5. #include "netuser.h"
  6. #include "files.h"
  7. #include "md5.h"
  8. #include "mailbox.h"
  9.  
  10.  
  11. #if !defined(_lint)
  12. static char rcsid[] OPTIONAL = "$Id: auth.c,v 1.3 1997/08/19 01:19:22 root Exp root $";
  13. #endif
  14.  
  15. extern char Whitespace[];
  16.  
  17. extern long btol (char *s);
  18. void usercvt (void);
  19. char *getsecurity (char *name, int32 *perms);
  20.  
  21.  
  22. #define lookupBUFSIZ    1024
  23.  
  24.  
  25. /* Read through FTPUSERS looking for user record
  26.  * Returns line which matches username, or NULLCHAR when no match.
  27.  * Each of the other variables must be copied before freeing the line.
  28.  */
  29. char *
  30. userlookup(username,password,directory,permission,ip_address)
  31. const char *username;
  32. char **password;
  33. char **directory;
  34. long   *permission;
  35. uint32 *ip_address;
  36. {
  37. FILE *fp, *fpsave = NULLFILE;
  38. char *buf;
  39. char *cp = NULLCHAR;
  40. int  wasanony = 0;
  41. char *universal = NULLCHAR;
  42.  
  43.     if ((fp = fopen (Userfile, READ_TEXT)) == NULLFILE)
  44.         /* Userfile doesn't exist */
  45.         return NULLCHAR;
  46.  
  47.     buf = mallocw (lookupBUFSIZ);
  48.     for ( ; ; )    {
  49.         if (fgets (buf, lookupBUFSIZ - 1, fp) == NULLCHAR)    {
  50.             if (fpsave)    {
  51.                 (void) fclose (fp);
  52.                 fp = fpsave;
  53.                 fpsave = NULLFILE;
  54.                 continue;
  55.             }
  56.             break;
  57.         }
  58.         if (!strnicmp (buf, "#include", 8))    {
  59.             rip (buf);
  60.             cp = skipwhite (&buf[8]);
  61.             fpsave = fp;
  62.             if((fp = fopen (cp, READ_TEXT)) == NULLFILE)    {
  63.                 fp = fpsave;
  64.                 fpsave = NULLFILE;
  65.             }
  66.             continue;
  67.         }
  68.         if (*buf == '#')
  69.             continue;    /* Comment */
  70.  
  71.         if ((cp = strpbrk (buf, " \t")) == NULLCHAR)
  72.             /* Bogus entry */
  73.             continue;
  74.         *cp++ = '\0';        /* Now points to password */
  75.         cp = skipwhite (cp);    /* It does now... KFU */
  76.  
  77.         if (stricmp (username, buf) == 0)
  78.             break;        /* Found user */
  79.         if (stricmp ("univperm", buf) == 0)
  80.             universal = strdup (cp);    /* remember their anon entry */
  81.     }
  82.     if (feof (fp))    {
  83.         if (universal == NULLCHAR)    {
  84.             /* username not found in file, nor was univperm */
  85.             if (fpsave)
  86.                 (void) fclose (fpsave);
  87.             (void) fclose (fp);
  88.             free (buf);
  89.             return NULLCHAR;
  90.         }
  91.         /* restore anonymous to the buffer */
  92.         strncpy (cp = buf, universal, lookupBUFSIZ);
  93.         wasanony = 1;
  94.     }
  95.     if (universal != NULLCHAR)
  96.         free (universal);
  97.     (void) fclose (fp);
  98.     if (fpsave)
  99.         (void) fclose (fpsave);
  100.  
  101.     if (cp == NULLCHAR)
  102.         return cp;
  103.  
  104.     if (password != NULL)
  105.         *password = cp;
  106.  
  107.     /* Look for space or tab after password field in file */
  108.     if ((cp = strpbrk (cp, " \t")) == NULLCHAR)    {
  109.         /* Invalid file entry */
  110.         free (buf);
  111.         return NULLCHAR;
  112.     }
  113.     *cp++ = '\0';    /* Now points to directory field */
  114.     cp = skipwhite (cp);
  115.  
  116.     if (*cp == '#')        { /* using a security level entry */
  117.         char *cp2, *path;
  118.         int32 perm = 0;
  119.         rip (cp);
  120.         if ((cp2 = strpbrk (++cp, " \t")) != NULLCHAR)
  121.             *cp2++ = 0;
  122.         path = getsecurity (cp--, &perm);
  123.         if (path != NULLCHAR)
  124.             sprintf(cp, "%s %ld", path, perm);
  125.     }
  126.     if (directory != NULL)
  127.         *directory = cp;
  128.  
  129.     if ((cp = strpbrk (cp, " \t")) == NULLCHAR)    {
  130.         /* Permission field missing */
  131.         free (buf);
  132.         return NULLCHAR;
  133.     }
  134.     *cp++ = '\0';    /* now points to permission field */
  135.     cp = skipwhite (cp);
  136.  
  137.     if (permission != NULL)    {
  138.         if (!strnicmp (cp, "0x", 2))
  139.             *permission = htol (cp);
  140.         else if (*cp == '%')
  141.             *permission = btol (cp);
  142.         else
  143.             *permission = atol (cp);
  144.         if (wasanony)
  145.             *permission |= WAS_ANONY;
  146.  
  147.         if (*permission & NO_SENDCMD)
  148.             *permission |= (NO_PBBSMAIL + NO_INETMAIL + NO_AMPRMAIL);
  149.  
  150.     }
  151.  
  152.     if ((cp = strpbrk (cp, " \t")) == NULLCHAR)    {
  153.         /* IP address missing */
  154.         if (ip_address != NULL)
  155.             *ip_address = 0L;
  156.     } else {
  157.         *cp++ = '\0';    /* now points at IP address field */
  158.         cp = skipwhite (cp);
  159.         if (ip_address != NULL)
  160.             *ip_address = resolve(cp);
  161.     }
  162.     return buf;
  163. }
  164.  
  165.  
  166. /* Subroutine for logging in the user whose name is name and password is pass.
  167.    The buffer path should be long enough to keep a line from the userfile.
  168.    If pwdignore is true, the password check will be overridden.
  169.    The return value is the permissions field or -1 if the login failed.
  170.    Path is set to point at the path field, and pwdignore will be true if no
  171.    particular password was needed for this user.
  172.  */
  173. long
  174. userlogin(name,pass,path,len,pwdignore)
  175. const char *name;
  176. char *pass;
  177. char **path;
  178. int len;            /* Length of buffer pointed at by *path */
  179. int *pwdignore;
  180. {
  181. char *buf;
  182. char *password;
  183. char *directory;
  184. long permission;
  185. int anonymous;
  186. char *cp;
  187. char hashpass[16];
  188. MD5_CTX md;
  189.  
  190.     if ((buf = userlookup (name, &password, &directory,
  191.         &permission, NULL)) == NULLCHAR)
  192.             return -1;
  193.  
  194.     anonymous = *pwdignore;
  195.     if (strcmp (password, "*") == 0)
  196.         anonymous = TRUE;    /* User ID is password-free */
  197.     if (!anonymous) {
  198.         if (readhex (hashpass, password, sizeof (hashpass)) != (int) sizeof (hashpass)){
  199.             /* Invalid hashed password in file */
  200.             free (buf);
  201.             return -1;
  202.         }
  203.         MD5Init (&md);
  204.         MD5Update (&md, (const unsigned char *) name, strlen (name));
  205.         MD5Update (&md, (unsigned char *) pass, strlen (pass));
  206.         MD5Final (&md);
  207.         if (memcmp (md.digest, hashpass, sizeof (hashpass)) != 0){
  208.             /* Incorrect password given */
  209.             free (buf);
  210.             return -1;
  211.         }
  212.     }
  213.     if ((int)strlen(directory) + 1 > len) {
  214.         /* not enough room for path */
  215.         free (buf);
  216.         return -1;
  217.     }
  218.  
  219.     strncpy (*path, directory, (unsigned) len);
  220.     /* Convert any backslashes to forward slashes, for backward
  221.      * compatibility with the old NET
  222.      */
  223.     while ((cp = strchr (*path, '\\')) != NULLCHAR)
  224.         *cp = '/';
  225.  
  226.     free (buf);
  227.     *pwdignore = anonymous;
  228.     /* Finally return the permission bits */
  229.     return permission;
  230. }
  231.  
  232.  
  233. /* MD5 hash plaintext passwords in a file */
  234. static void
  235. usercvtfile(const char *file, int recursing)
  236. {
  237. FILE *fp,*fptmp;
  238. char *buf, *cp;
  239. char hexbuf[16];
  240. int needsit = 0;
  241. int len,nlen,plen,i;
  242. char *pass;
  243. MD5_CTX md;
  244.  
  245.     if ((fp = fopen (file, READ_TEXT)) == NULLFILE)
  246.         return;        /* file doesn't exist */
  247.  
  248.     tprintf ("%sEncoding passwords in %s\n", (recursing) ? "" : "\n", file);
  249.     buf = mallocw (BUFSIZ);
  250.     while (fgets (buf, BUFSIZ, fp) != NULLCHAR){
  251.         rip (buf);
  252.         len = (int) strlen (buf);
  253.         if (len == 0)
  254.             continue;    /* Blank line */
  255.  
  256.         if (!strnicmp (buf, "#include", 8))    {
  257.             cp = skipwhite (&buf[8]);
  258.             usercvtfile (cp, 1);
  259.             continue;
  260.         }
  261.         if (*buf == '#')
  262.             continue;    /* Comment line */
  263.  
  264.         if ((nlen = (int) strcspn (buf,Whitespace)) == len)
  265.             continue;    /* No end to the name! */
  266.  
  267.         /* Skip whitespace between name and pass */
  268.         for (pass = &buf[nlen]; isspace (*pass); pass++)
  269.             ;
  270.         if(*pass != '\0' && *pass != '*'
  271.          && readhex (hexbuf, pass, sizeof (hexbuf)) != 16){
  272.             needsit = 1;
  273.             break;
  274.         }
  275.     }
  276.     if(!needsit){
  277.         /* Everything is in order */
  278.         (void) fclose (fp);
  279.         free (buf);
  280.         return;
  281.     }
  282.     /* At least one entry needs its password hashed */
  283.     rewind (fp);
  284.     fptmp = tmpfile();
  285.     if (fptmp == NULLFILE)    {
  286.         printf ("Can't rewrite %s: can't create a tempfile!\n", file);
  287.         (void) fclose (fp);
  288.         free (buf);
  289.         return;
  290.     }
  291.     while (fgets (buf, BUFSIZ, fp) != NULLCHAR)    {
  292.         rip (buf);
  293.         if ((len = (int) strlen (buf)) == 0 || *buf == '#'
  294.          || (nlen = (int) strcspn (buf, Whitespace)) == len){
  295.             /* Line is blank, a comment or unparseable;
  296.              * copy unchanged
  297.              */
  298.             fputs (buf, fptmp);
  299.             fputc ('\n', fptmp);
  300.             continue;
  301.         }
  302.         /* Skip whitespace between name and pass */
  303.         for (pass = &buf[nlen]; isspace (*pass); pass++)
  304.             ;
  305.  
  306.         if(*pass == '\0' || *pass == '*'
  307.          || (plen = (int) strcspn (pass, Whitespace)) == (int)strlen (pass)
  308.          || readhex (hexbuf, pass, sizeof (hexbuf)) == (int)sizeof (hexbuf)){
  309.             /* Other fields are missing, no password is required,
  310.              * or password is already hashed; copy unchanged
  311.              */
  312.             fputs (buf, fptmp);
  313.             fputc ('\n', fptmp);
  314.             continue;
  315.         }
  316.         MD5Init (&md);
  317.         MD5Update (&md, (unsigned char *) buf, (unsigned int)nlen);    /* Hash name */
  318.         MD5Update (&md, (unsigned char *) pass, (unsigned int)plen);    /* Hash password */
  319.         MD5Final (&md);
  320.         fwrite (buf, 1, (unsigned int)nlen, fptmp);    /* Write name */
  321.         fputc (' ', fptmp);        /* and space */
  322.         for (i = 0; i < 16; i++)    /* Write hashed password */
  323.             fprintf (fptmp, "%02x", md.digest[i] & 0xff);
  324.         fputs (&pass[plen], fptmp);    /* Write remainder of line */
  325.         fputc ('\n', fptmp);
  326.     }
  327.     /* Now copy the temp file back into the userfile */
  328.     (void) fclose (fp);
  329.     rewind (fptmp);
  330.     if ((fp = fopen (file, WRITE_TEXT)) == NULLFILE)    {
  331.         printf ("Can't rewrite %s\n", file);
  332.         free (buf);
  333.         return;
  334.     }
  335.     while (fgets (buf, BUFSIZ, fptmp) != NULLCHAR)
  336.         fputs (buf, fp);
  337.     (void) fclose (fp);
  338.     (void) fclose (fptmp);
  339.     free (buf);
  340. }
  341.  
  342.  
  343. /* MD5 hash plaintext passwords in user file */
  344. void
  345. usercvt()
  346. {
  347.     usercvtfile (Userfile, 0);
  348. }
  349.  
  350.  
  351.  
  352.